/*
 * TIMER.c
 *
 * Created: 22/04/2012 11:28:39 AM
 *  Author: Richard
 */ 
#include "TIMER.h"


static uint16 TIMER__u16CurrentTime;

static struct
{
	uint16 u16CurrentTime;
	//uint16 u16Timeout;
	uint16 u16Period;
	TIMER_tenTimerMode enMode;
	void (*tFuncCallback)(void);	
} TIMER__astTimerProperties[TIMER_nenNumberOfChannels];	

void TIMER_vReset( void )
{
	TIMER_tenChannels enChannel;
	
	TIMER__u16CurrentTime = 0;
	for( enChannel = (TIMER_tenChannels)0; enChannel < TIMER_nenNumberOfChannels; enChannel++ )
	{
		TIMER__astTimerProperties[enChannel].u16CurrentTime	= 0;
		TIMER__astTimerProperties[enChannel].u16Period		= 0;
		TIMER__astTimerProperties[enChannel].enMode			= TIMER_nenStopped;
		TIMER__astTimerProperties[enChannel].tFuncCallback	= 0;
	}		
}	

void TIMER_vInterruptHook( void )
{
	//TIMER__u16CurrentTime++;
	if( TIMER__astTimerProperties[0].u16CurrentTime != 0 )
	{
		TIMER__astTimerProperties[0].u16CurrentTime--;	
	}
}	

bool TIMER_boStartTimer( const TIMER_tenChannels enChannel,
						 const uint16 u16TimeoutMs,
						 const TIMER_tenTimerMode enMode,
						 void (*tFuncCallback)(void) )
{
	bool boRetVal = false;
	
	if( enChannel < TIMER_nenNumberOfChannels )
	{
		if( TIMER__astTimerProperties[enChannel].enMode == TIMER_nenStopped )
		{
			TIMER__astTimerProperties[enChannel].u16Period		= u16TimeoutMs;
			TIMER__astTimerProperties[enChannel].u16CurrentTime = u16TimeoutMs;
			TIMER__astTimerProperties[enChannel].enMode			= enMode;
			TIMER__astTimerProperties[enChannel].tFuncCallback  = tFuncCallback;
			boRetVal = true;
		}			
	}	
	
	return boRetVal;	
}	

void TIMER_vStopTimer( const TIMER_tenChannels enChannel )
{
	if( enChannel < TIMER_nenNumberOfChannels )
	{
		TIMER__astTimerProperties[enChannel].enMode = TIMER_nenStopped;
	}		
}	

bool TIMER_boIsTimerActive( const TIMER_tenChannels enChannel )
{
	bool boRetVal = false;
	
	if( enChannel < TIMER_nenNumberOfChannels )
	{
		boRetVal = ( TIMER__astTimerProperties[enChannel].enMode != TIMER_nenStopped );
	}	
	
	return boRetVal;	
}								 

void TIMER_vBackgroundTask( void )
{
	TIMER_tenChannels enChannel;
	bool boFireCallback;
	
	for( enChannel = (TIMER_tenChannels)0; enChannel < TIMER_nenNumberOfChannels; enChannel++ )
	{
		boFireCallback = false;
		if( TIMER__astTimerProperties[enChannel].u16CurrentTime == 0 )
		{
			if( TIMER__astTimerProperties[enChannel].enMode == TIMER_nenOneShot )
			{
				TIMER__astTimerProperties[enChannel].enMode = TIMER_nenStopped;
				boFireCallback = true;
			}
			else if( TIMER__astTimerProperties[enChannel].enMode == TIMER_nenFreeRunning )
			{
				TIMER__astTimerProperties[enChannel].u16CurrentTime = TIMER__astTimerProperties[enChannel].u16Period;
				boFireCallback = true;
			}	
			
			if( ( boFireCallback == true ) && ( TIMER__astTimerProperties[enChannel].tFuncCallback != 0 ) )
			{
				TIMER__astTimerProperties[enChannel].tFuncCallback();
			}									
		}			
	}		
}	


